package osmedile.intellij.javadochelper;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

/**
 * @author Olivier Smedile
 * @version $Id: JHConfig.java 71 2008-09-29 19:19:37Z osmedile $
 */
public class JHConfig {
    private JPanel rootPanel;
    private JTable classTagTable;
    private JButton classTagRemoveBt;
    private JButton classTagAddBt;
    private JCheckBox removeIfDocMatchChk;
    private JCheckBox addIfDocDiffersChk;
    private JButton resetDefaultConfBt;
    private JCheckBox addIfNoDocChk;

    private ClassTagModel classTagModel;

    private AddClassTagDialog addClassTagDialog;

    public String[] COL_TIPS =
            {"<html>If <b>false</b>, this tag won't be processed</html>",
             "Name of the tag",
             "Value of the tag",
             "<html>If another tags with same name exists, then you can choose the behavior here.<br /><ul><li><b>Add</b>: always add the tag <i>(except if value is same, see next column for detauls)</i></li><li><b>Don't add</b>: ignore this tag</li><li><b>Replace all</b>: all existant tags with same will be deleted and this tag will be added.</li></ul></html>",
             "<html>If another tag with same name (case sensitive) and same value exists, <br />then original tag is always kept and this tag won't be added. <br />If <b>true</b>, then tag value comparison is case insensitive.</html>"};

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        rootPanel = new JPanel();
        rootPanel.setLayout(new GridBagLayout());
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new GridBagLayout());
        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 3;
        gbc.weightx = 0.1;
        gbc.weighty = 0.3;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(10, 0, 10, 0);
        rootPanel.add(panel1, gbc);
        panel1.setBorder(BorderFactory.createTitledBorder("Javadoc class tags"));
        classTagRemoveBt = new JButton();
        classTagRemoveBt.setText("-");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        panel1.add(classTagRemoveBt, gbc);
        final JScrollPane scrollPane1 = new JScrollPane();
        scrollPane1.setInheritsPopupMenu(false);
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 4;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        panel1.add(scrollPane1, gbc);
        classTagTable = new JTable();
        scrollPane1.setViewportView(classTagTable);
        classTagAddBt = new JButton();
        classTagAddBt.setHorizontalAlignment(0);
        classTagAddBt.setHorizontalTextPosition(0);
        classTagAddBt.setText("+");
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 0;
        panel1.add(classTagAddBt, gbc);
        final JPanel spacer1 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel1.add(spacer1, gbc);
        resetDefaultConfBt = new JButton();
        resetDefaultConfBt.setText("Reset default configuration");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.WEST;
        rootPanel.add(resetDefaultConfBt, gbc);
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.weighty = 0.1;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.VERTICAL;
        gbc.insets = new Insets(10, 0, 10, 0);
        rootPanel.add(panel2, gbc);
        panel2.setBorder(BorderFactory.createTitledBorder("{@inheritDoc} behavior"));
        removeIfDocMatchChk = new JCheckBox();
        removeIfDocMatchChk.setHorizontalAlignment(10);
        removeIfDocMatchChk.setHorizontalTextPosition(4);
        removeIfDocMatchChk.setText("Remove javadoc if it matches parent javadoc.");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.WEST;
        panel2.add(removeIfDocMatchChk, gbc);
        addIfDocDiffersChk = new JCheckBox();
        addIfDocDiffersChk.setHorizontalTextPosition(4);
        addIfDocDiffersChk.setSelected(false);
        addIfDocDiffersChk.setText("<html>Add <i>{@inheritDoc}</i> at top if javadoc differs</html>");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.WEST;
        panel2.add(addIfDocDiffersChk, gbc);
        addIfNoDocChk = new JCheckBox();
        addIfNoDocChk.setText("<html>Add <i>{@inheritDoc}</i> if there is no javadoc</html>");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.anchor = GridBagConstraints.WEST;
        panel2.add(addIfNoDocChk, gbc);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return rootPanel;
    }

    public class ClassTagModel extends AbstractTableModel {
        /**
         * LinkedHashMap to maintain insertion order
         */
        private java.util.List<ClassTag> classTags;


        public java.util.List<ClassTag> getClassTags() {
            return classTags;
        }

        public String[] COL_NAMES =
                {"Active", "Tag", "Value", "If other tags with same name",
                 "Ignore value case"};

        public ClassTagModel() {
            this.classTags = new ArrayList<ClassTag>();
        }

        public void setClassTags(java.util.List<ClassTag> classTags) {
            if (classTags == null) {
                throw new IllegalArgumentException("classTags is null");
            }
            this.classTags.clear();
            this.classTags.addAll(classTags);
            fireTableDataChanged();
        }

        @Override
        public String getColumnName(int column) {
            return COL_NAMES[column];
        }

        @Override
        public Class<?> getColumnClass(int colIdx) {
            if (colIdx == 1 || colIdx == 2) {
                return String.class;
            } else if (colIdx == 3) {
                return ClassTag.REPLACE_MODE.class;
            } else {
                return Boolean.class;
            }
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        public int getRowCount() {
            return classTags.size();
        }

        public int getColumnCount() {
            return COL_NAMES.length;
        }

        public Object getValueAt(int rowIndex, int colIdx) {
            if (colIdx == 0) {
                return classTags.get(rowIndex).getActive();
            } else if (colIdx == 1) {
                return classTags.get(rowIndex).getName();
            } else if (colIdx == 2) {
                return classTags.get(rowIndex).getValue();
            } else if (colIdx == 3) {
                return classTags.get(rowIndex).getReplaceMode().toString();
            } else if (colIdx == 4) {
                return classTags.get(rowIndex).getIgnoreCase();
            }
            return "Invalid column index";
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            if (columnIndex == 0) {
                Boolean val = (Boolean) aValue;
                classTags.get(rowIndex).setActive(val);
            } else if (columnIndex == 1) {
                String val = (String) aValue;
                classTags.get(rowIndex).setName(val);
            } else if (columnIndex == 2) {
                String val = (String) aValue;
                classTags.get(rowIndex).setValue(val);
            } else if (columnIndex == 3) {
                ClassTag.REPLACE_MODE val = (ClassTag.REPLACE_MODE) aValue;
                classTags.get(rowIndex).setReplaceMode(val);
            } else if (columnIndex == 4) {
                Boolean val = (Boolean) aValue;
                classTags.get(rowIndex).setIgnoreCase(val);
            }
            fireTableRowsUpdated(rowIndex, rowIndex);
            //"Invalid column index";
        }

        public void add(ClassTag classTag) {
            if (!classTags.contains(classTag)) {
                classTags.add(classTag);
//                fireTableRowsInserted(getRowCount(), getRowCount());
                fireTableDataChanged();
            }
        }

        public void remove(int index) {
            classTags.remove(index);
            fireTableDataChanged();
        }
    }

    public JHConfig() {
        classTagModel = new ClassTagModel();
        classTagTable.setModel(classTagModel);
        classTagTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        JComboBox comboBox = new JComboBox();
        final DefaultComboBoxModel defaultComboBoxModel1 =
                new DefaultComboBoxModel();
        defaultComboBoxModel1.addElement(ClassTag.REPLACE_MODE.ADD);
        defaultComboBoxModel1.addElement(ClassTag.REPLACE_MODE.DONT_ADD);
        defaultComboBoxModel1.addElement(ClassTag.REPLACE_MODE.REPLACE_ALL);
        comboBox.setModel(defaultComboBoxModel1);

        classTagTable.setDefaultEditor(ClassTag.REPLACE_MODE.class,
                new DefaultCellEditor(comboBox));

        classTagTable.setTableHeader(
                new JTableHeader(classTagTable.getColumnModel()) {
                    @Override
                    public String getToolTipText(MouseEvent e) {
                        int index =
                                columnModel.getColumnIndexAtX(e.getPoint().x);
                        int realIndex =
                                columnModel.getColumn(index).getModelIndex();
                        return COL_TIPS[realIndex];
                    }
                });

        addClassTagDialog = new AddClassTagDialog();
        //TODO replace this with listener
        addClassTagDialog.setJhConfig(this);
        addClassTagDialog.pack();
        addClassTagDialog.setLocationRelativeTo(this.getRootComponent());


        classTagAddBt.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addClassTagDialog.reset();
                addClassTagDialog.setVisible(true);
            }
        });

        classTagRemoveBt.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                classTagModel.remove(classTagTable
                        .getSelectionModel().getMinSelectionIndex());

            }
        });

        resetDefaultConfBt.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int resp =
                        JOptionPane
                                .showConfirmDialog(getRootComponent(), "Reset configuration to default",
                                        "Javadoc Helper", JOptionPane.YES_NO_OPTION);
                if (JOptionPane.OK_OPTION == resp) {
                    ConfigImpl config = new ConfigImpl();
                    setData(config);
                }
            }
        });

    }

    public ClassTagModel getClassTagModel() {
        return classTagModel;
    }

    // --------------------- METHODS ---------------------

    /**
     * Fill config parameter with visual parameter set on form
     *
     * @param config
     */
    public void getData(IConfig config) {
        config.setAddIfDocDiffers(addIfDocDiffersChk.isSelected());
        config.setRemoveIfDocMatch(removeIfDocMatchChk.isSelected());
        config.setAddInheritDocIfNoDoc(
                addIfNoDocChk.isSelected());
        config.setClassTags(classTagModel.getClassTags());
    }

    public JComponent getRootComponent() {
        return this.rootPanel;
    }

    public boolean isModified(IConfig config) {
        return addIfDocDiffersChk.isSelected() != config.getAddIfDocDiffers() ||
                removeIfDocMatchChk.isSelected() !=
                        config.getRemoveIfDocMatch() ||
                addIfNoDocChk.isSelected() !=
                        config.getAddInheritDocIfNoDoc() ||
                !classTagModel.getClassTags().equals(config.getClassTags());
    }

    public void setData(IConfig config) {
        addIfDocDiffersChk.setSelected(config.getAddIfDocDiffers());
        removeIfDocMatchChk.setSelected(config.getRemoveIfDocMatch());
        addIfNoDocChk
                .setSelected(config.getAddInheritDocIfNoDoc());
        classTagModel.setClassTags(config.getClassTags());
    }
}
